﻿using System;
using System.Configuration;

namespace Sherwood.Configuration
{
    ///<summary>
    /// Specifies a type configured in a <see cref="ITypeMappingConfiguration{T}"/>.
    ///</summary>
    ///<typeparam name="T">The configured type will be assignable from this type</typeparam>
    public class ConfiguredType<T> where T : class
    {
        ///<summary>
        /// Create an instance with name and type
        ///</summary>
        ///<param name="name">The configured name</param>
        ///<param name="type">The configured type</param>
        ///<exception cref="ArgumentNullException">One of the arguments is null</exception>
        public ConfiguredType(string name, Type type)
        {
            if (name == null) throw new ArgumentNullException("name");
            if (type == null) throw new ArgumentNullException("type");
            Name = name;
            Type = type;
        }

        ///<summary>
        /// Create an instance with name and type
        ///</summary>
        ///<param name="name">The configured name</param>
        ///<param name="instance">An instance</param>
        ///<exception cref="ArgumentNullException">One of the arguments is null</exception>
        public ConfiguredType(string name, T instance)
        {
            if (name == null) throw new ArgumentNullException("name");
            if (instance== null) throw new ArgumentNullException("instance");
            Name = name;
            _instance = instance;
            Type = instance.GetType();
        }

        ///<summary>
        /// The configured name
        ///</summary>
        public string Name { get; private set; }

        /// <summary>
        /// The configured type
        /// </summary>
        public Type Type { get; private set; }

        private T _instance;
        ///<summary>
        /// Returns a "singleton" unique for this instance of ConfiguredType
        ///</summary>
        ///<exception cref="ConfigurationErrorsException">Type does not have a default constructor</exception>
        public T Instance
        {
            get
            {
                if (_instance != null)
                    return _instance;
                _instance = DependencyInjection.Resolve<T>();
                return _instance;
            }
        }
    }
}